package com.it.tydic.estate.common.aop;

import java.lang.reflect.Method;


import com.it.tydic.estate.common.annotation.ControllerDesc;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Aspect  
public class ExceptionAspcet {  
	
	private static Logger logger = LoggerFactory.getLogger(ExceptionAspcet.class);
  
	 /** 
     * Pointcut 
     * 定义Pointcut，Pointcut的名称为aspectjMethod()，此方法没有返回值和参数 
     * 该方法就是一个标识，不进行调用 
     */  
	//@Pointcut("execution(* *Controller(..))")
	@Pointcut("within(com.it.tydic.estate.module.controller..*)")
    private void aspectjMethod(){};  
      
    /**  
     * Before 
     * 在核心业务执行前执行，不能阻止核心业务的调用。 
     * @param joinPoint  
     */    
   @Before("aspectjMethod()")
    public void beforeAdvice(JoinPoint joinPoint) {    
        System.out.println("-----beforeAdvice().invoke-----");  
        System.out.println(" 此处意在执行核心业务逻辑前，做一些安全性的判断等等");
        System.out.println(" 可通过joinPoint来获取所需要的内容");  
        System.out.println("-----End of beforeAdvice()------");  
    	logger.debug("-----beforeAdvice()-----");
    }
      
    /**  
     * After  
     * 核心业务逻辑退出后（包括正常执行结束和异常退出），执行此Advice 
     * @param joinPoint 
     */  
    @After(value = "aspectjMethod()")
    public void afterAdvice(JoinPoint joinPoint) {    
        System.out.println("-----afterAdvice().invoke-----");  
        System.out.println(" 此处意在执行核心业务逻辑之后，做一些日志记录操作等等");  
        System.out.println(" 可通过joinPoint来获取所需要的内容");  
        System.out.println("-----End of afterAdvice()------");  
    	logger.debug("-----afterAdvice()-----");
    }
  
    /**  
     * Around  
     * 手动控制调用核心业务逻辑，以及调用前和调用后的处理, 
     *  
     * 注意：当核心业务抛异常后，立即退出，转向AfterAdvice 
     * 执行完AfterAdvice，再转到ThrowingAdvice 
     * @param pjp 
     * @return 
     * @throws Throwable 
     */   
   /* @Around(value = "aspectjMethod()")    
    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {    
        System.out.println("-----aroundAdvice().invoke-----");  
        System.out.println(" 此处可以做类似于Before Advice的事情");  
          
        //调用核心逻辑  
        Object retVal = pjp.proceed();
        System.out.println(" 此处可以做类似于After Advice的事情");  
        System.out.println("-----End of aroundAdvice()------");  
        return retVal; 
    	logger.debug("-----aroundAdvice()-----");
    	//调用核心逻辑  
        Object retVal = pjp.proceed();
        return retVal;
    }*/    
      
    /**  
     * AfterReturning  
     * 核心业务逻辑调用正常退出后，不管是否有返回值，正常退出后，均执行此Advice 
     * @param joinPoint 
     */   
    /*@AfterReturning(value = "aspectjMethod()", returning = "retVal")    
    public void afterReturningAdvice(JoinPoint joinPoint, String retVal) {    
        System.out.println("-----afterReturningAdvice().invoke-----");  
        System.out.println("Return Value: " + retVal);   
        System.out.println(" 此处可以对返回值做进一步处理");  
        System.out.println(" 可通过joinPoint来获取所需要的内容");  
        System.out.println("-----End of afterReturningAdvice()------");
    	logger.debug("-----afterReturningAdvice()-----");
    }*/  
    
    @AfterThrowing(value = "aspectjMethod()", throwing = "e")    
    public void afterThrowingAdvice(JoinPoint joinPoint, Exception e) throws ClassNotFoundException{    
		String des = getControllerMethodDescription(joinPoint);
		logger.error(des);
        logger.error("-------------------afterThrowing.handler.start-------------------");  
        logger.error("异常名称：" + e.getClass().toString());  
        logger.error("e.getMessage():" + e.getMessage());  
        logger.error("-------------------afterThrowing.handler.end-------------------");  
  
     
    }
    
    /** 
     * 获取方法名和参数 
     * @author lyl 
     * @param joinPoint 
     * @return 
     */  
    private String getMethodNameAndArgs(JoinPoint joinPoint){  
        Object[] args = joinPoint.getArgs();  
        StringBuffer sb = new StringBuffer("请求方法：");  
        sb.append(joinPoint.getTarget().getClass().getName() + "."  
                + joinPoint.getSignature().getName() + "(");  
        for (int i = 0; i < args.length; i++) {  
            sb.append("arg[" + i + "]: " + args[i] + ",");  
        }  
        if (args.length > 0) {  
            sb.deleteCharAt(sb.length() - 1);  
        }  
        sb.append(")");  
        return sb.toString();  
    }
    
    /** 
     * 获取注解中对方法的描述信息 用于Controller层注解 
     * 
     * @param joinPoint 切点 
     * @return 方法描述 
     * @throws ClassNotFoundException 
     * @throws Exception 
     */  
    public static String getControllerMethodDescription(JoinPoint joinPoint) throws ClassNotFoundException{  
        String targetName = joinPoint.getTarget().getClass().getName();  
        String methodName = joinPoint.getSignature().getName();  
        Object[] arguments = joinPoint.getArgs();  
        Class targetClass = Class.forName(targetName);  
        Method[] methods = targetClass.getMethods();  
        String description = "";  
        for (Method method : methods) {  
            if (method.getName().equals(methodName)) {  
                Class[] clazzs = method.getParameterTypes();  
                if (clazzs.length == arguments.length) {  
                	if(method != null && method.getAnnotation(ControllerDesc.class) != null) {
                		description = method.getAnnotation(ControllerDesc.class).description();
                		break;  
                	}
                }  
            }  
        }  
        return description;  
    }

}  